---
title: "Messages"
sidebarTitle: "Messages"
description: "Reference for Sequin's CDC messages."
---

Sequin converts Postgres changes into JSON messages that are delivered to your sinks. Each message contains the current record, any previous values, the action that occurred, and metadata about the event.

<Note>
You can apply a [transform](/reference/transforms) to the message to modify the data before it is delivered to your sink.
</Note>

<ResponseExample>
  ```json Insert Example
  {
    "record": {
      "id": 1234,
      "customer_id": 789,
      "product": "Wireless Headphones",
      "quantity": 1,
      "price": 199.99,
      "status": "pending",
      "created_at": "2024-10-28T21:37:01.127470Z",
      "updated_at": "2024-10-28T21:37:01.127470Z"
    },
    "changes": null,
    "action": "insert",
    "metadata": {
      "table_schema": "public",
      "table_name": "orders",
      "idempotency_key": "c2VxdWluc3RyZWFtLmNvbS9jYXJlZXJz",
      "commit_timestamp": "2024-10-28T21:37:01.127470Z",
      "commit_lsn": 123456789,
      "commit_idx": 1,
      "database_name": "myapp-prod", // deprecated
      "consumer": {
        "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
        "name": "orders_kafka",
        "annotations": {"my-custom-key": "my-custom-value"}
      },
      "database": {
        "id": "12345678-9abc-def0-1234-56789abcdef0",
        "name": "myapp-prod",
        "annotations": {"my-custom-key": "my-custom-value"},
        "database": "myapp-prod",
        "hostname": "db.example.com"
      },
      "enrichment": {
        "account_name": "Acme, Inc.",
        "customer_name": "Paul Atreides"
      },
      "transaction_annotations": {
        "username": "paul.atreides",
        "source": "web_ui",
        "request_id": "req_123"
      }
    }
  }
  ```

  ```json Update Example
  {
    "record": {
      "id": 1234,
      "customer_id": 789,
      "product": "Wireless Headphones",
      "quantity": 1,
      "price": 199.99,
      "status": "shipped",
      "created_at": "2024-10-28T21:37:01.127470Z",
      "updated_at": "2024-10-28T21:39:21.127470Z"
    },
    "changes": {
      "status": "pending",
      "updated_at": "2024-10-28T21:37:01.127470Z"
    },
    "action": "update",
    "metadata": {
      "table_schema": "public",
      "table_name": "orders",
      "idempotency_key": "c2VxdWluc3RyZWFtLmNvbS9jYXJlZXJz",
      "commit_timestamp": "2024-10-28T21:39:21.127470Z",
      "commit_lsn": 123456790,
      "commit_idx": 1,
      "database_name": "myapp-prod", // deprecated
      "consumer": {
        "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
        "name": "orders_kafka",
        "annotations": {"my-custom-key": "my-custom-value"}
      },
      "enrichment": {
        "account_name": "Acme, Inc.",
        "customer_name": "Paul Atreides"
      },
      "database": {
        "id": "12345678-9abc-def0-1234-56789abcdef0",
        "name": "myapp-prod",
        "annotations": {"my-custom-key": "my-custom-value"},
        "database": "myapp-prod",
        "hostname": "db.example.com"
      }
    }
  }
  ```

  ```json Delete Example
  {
    "record": {
      "id": 1234,
      "customer_id": 789,
      "product": "Wireless Headphones",
      "quantity": 1,
      "price": 199.99,
      "status": "shipped",
      "created_at": "2024-10-28T21:37:01.127470Z",
      "updated_at": "2024-10-28T21:39:21.127470Z"
    },
    "changes": null,
    "action": "delete",
    "metadata": {
      "table_schema": "public",
      "table_name": "orders",
      "idempotency_key": "c2VxdWluc3RyZWFtLmNvbS9jYXJlZXJz",
      "commit_timestamp": "2024-10-28T21:40:00.127470Z",
      "commit_lsn": 123456791,
      "commit_idx": 1,
      "database_name": "myapp-prod", // deprecated
      "consumer": {
        "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
        "name": "orders_kafka",
        "annotations": {"my-custom-key": "my-custom-value"}
      },
      "enrichment": {
        "account_name": "Acme, Inc.",
        "customer_name": "Paul Atreides"
      },
      "database": {
        "id": "12345678-9abc-def0-1234-56789abcdef0",
        "name": "myapp-prod",
        "annotations": {"my-custom-key": "my-custom-value"},
        "database": "myapp-prod",
        "hostname": "db.example.com"
      }
    }
  }
  ```

  ```json Read Example (Backfill)
  {
    "record": {
      "id": 1234,
      "customer_id": 789,
      "product": "Wireless Headphones",
      "quantity": 1,
      "price": 199.99,
      "status": "shipped",
      "created_at": "2024-10-28T21:37:01.127470Z",
      "updated_at": "2024-10-28T21:39:21.127470Z"
    },
    "changes": null,
    "action": "read",
    "metadata": {
      "table_schema": "public",
      "table_name": "orders",
      "idempotency_key": "c2VxdWluc3RyZWFtLmNvbS9jYXJlZXJz",
      "commit_timestamp": "2024-10-28T21:39:21.127470Z",
      "commit_lsn": 123456792,
      "commit_idx": 1,
      "database_name": "myapp-prod", // deprecated
      "consumer": {
        "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
        "name": "orders_kafka",
        "annotations": {"my-custom-key": "my-custom-value"}
      },
      "enrichment": {
        "account_name": "Acme, Inc.",
        "customer_name": "Paul Atreides"
      },
      "database": {
        "id": "12345678-9abc-def0-1234-56789abcdef0",
        "name": "myapp-prod",
        "annotations": {"my-custom-key": "my-custom-value"},
        "database": "myapp-prod",
        "hostname": "db.example.com"
      }
    }
  }
  ```
</ResponseExample>

<ResponseField name="record" type="object">
  The current state of the row. Contains all column values.
</ResponseField>

<ResponseField name="changes" type="object">
  For `update` operations, contains the previous values of changed fields. For `insert` and `delete` operations, this field is null.
</ResponseField>

<ResponseField name="action" type="string">
  The type of change that occurred. One of:
  - `insert`: A new row was created
  - `update`: An existing row was modified
  - `delete`: A row was deleted
  - `read`: A row was read during a [backfill](/reference/backfills)
</ResponseField>

<ResponseField name="metadata" type="object">
  Additional context about the change.
  <Expandable title="metadata fields" defaultOpen="true">
    <ResponseField name="metadata.table_schema" type="string">
      The Postgres schema containing the table (e.g., "public").
    </ResponseField>

    <ResponseField name="metadata.table_name" type="string">
      The name of the table that was changed.
    </ResponseField>

    <ResponseField name="metadata.commit_timestamp" type="string">
      ISO 8601 timestamp when the change was committed to the database.
    </ResponseField>

    <ResponseField name="metadata.idempotency_key" type="string">
      Opaque string which is [unique to this record/transaction](#idempotency).
    </ResponseField>

    <ResponseField name="metadata.commit_lsn" type="integer">
      The log sequence number of the transaction that made this change.
    </ResponseField>

    <ResponseField name="metadata.commit_idx" type="integer">
      The index of this change within the transaction.
    </ResponseField>

    <ResponseField name="metadata.database_name" type="string">
      _Deprecated_. The name of the database that was changed.
    </ResponseField>

    <ResponseField name="metadata.transaction_annotations" type="object">
      User-provided context about the transaction. Contains arbitrary JSON data set via `pg_logical_emit_message`. See [Transaction annotations](/reference/annotations) for details.
    </ResponseField>

    <ResponseField name="metadata.consumer" type="object">
      Information about the consumer receiving this message.
    </ResponseField>

    <ResponseField name="metadata.consumer.id" type="string">
      Unique identifier for the consumer.
    </ResponseField>

    <ResponseField name="metadata.consumer.name" type="string">
      Name of the consumer.
    </ResponseField>

    <ResponseField name="metadata.consumer.annotations" type="object">
      Additional metadata you attached to the consumer.
    </ResponseField>

    <ResponseField name="metadata.enrichment" type="object">
      Enrichment results from the [enrichment function](/reference/enrichment) for this message.
    </ResponseField>

    <ResponseField name="metadata.database" type="object">
      Information about the database that was changed.
    </ResponseField>

    <ResponseField name="metadata.database.id" type="string">
      Unique identifier for the database.
    </ResponseField>

    <ResponseField name="metadata.database.name" type="string">
      Name of the database.
    </ResponseField>

    <ResponseField name="metadata.database.annotations" type="object">
      Additional metadata you attached to the database.
    </ResponseField>

    <ResponseField name="metadata.database.database" type="string">
      The database name.
    </ResponseField>

    <ResponseField name="metadata.database.hostname" type="string">
      The hostname of the database server.
    </ResponseField>
  </Expandable>
</ResponseField>

## Idempotency

The `metadata` of each message includes an `idempotency_key` which your application can use to reject any [possible duplicate messages](/reference/sinks/overview#delivery-guarantees).

For regular changes (non-backfill), the idempotency key is based on the transaction's position in the database log and its position within that transaction.

For backfill messages, the key is based on the backfill's unique identifier and the primary key values of the record being processed.

## Related

<CardGroup>
  <Card title="Transforms" icon="pencil" href="/reference/transforms">
    Learn how to transform payloads before they are sent to your destination.
  </Card>
  <Card title="Filters" icon="filter" href="/reference/filters">
    Learn how to filter messages before they are sent to your destination.
  </Card>
  <Card title="Routing" icon="route" href="/reference/routing">
    Learn how to route messages to different sinks based on their content.
  </Card>
  <Card title="Backfills" icon="clock-rotate-left" href="/reference/backfills">
    Learn how to backfill data from your database to your sinks.
  </Card>
</CardGroup>
